package org.wattdepot.gdata.kukuicup.service;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.Link;
import com.google.gdata.data.batch.BatchOperationType;
import com.google.gdata.data.batch.BatchStatus;
import com.google.gdata.data.batch.BatchUtils;
import com.google.gdata.data.spreadsheet.CellEntry;
import com.google.gdata.data.spreadsheet.CellFeed;

/**
 * Supports updating one or more cells in a given spreadsheet.
 * @author Philip Johnson
 */
public class GDataBatchRequest {
  
  /** The GData service specifying the credentials for updating. */
  private GDataService service;
  /** The CellFeed instance that will accumulate the batched requests. */
  private CellFeed batchRequest = new CellFeed();
  /** The URL of the spreadsheet to update. */
  private URL spreadsheetURL;
  private List<String> batchIDs = new ArrayList<String>();
  
  /**
   * Create a new GDataUpdate instance that can be used to update the passed service. 
   * @param service The gdata service.
   * @param spreadsheetURL The URL of the spreadsheet to update. 
   */
  public GDataBatchRequest(GDataService service, URL spreadsheetURL) {
    this.service = service;
    this.spreadsheetURL = spreadsheetURL;
  }
  
  /**
   * Accepts a request to update a (row, column) with the passed value. 
   * @param row The row to update. 
   * @param column The column to update.
   * @param value The value to be placed in the (row, column) cell.
   * @throws Exception If problems occur specifying this update. 
   */
  public void addRequest(int row, int column, String value) throws Exception {
    String batchId = "R" + row + "C" + column;
    if (batchIDs.contains(batchId)) {
      throw new RuntimeException("Duplicate batchID found: " + batchId);
    }
    URL entryUrl = new URL(spreadsheetURL.toString() + "/" + batchId);
    CellEntry entry = service.getSpreadsheetService().getEntry(entryUrl, CellEntry.class);
    entry.changeInputValueLocal(value);
    BatchUtils.setBatchId(entry, batchId);
    BatchUtils.setBatchOperationType(entry, BatchOperationType.UPDATE);
    batchRequest.getEntries().add(entry);
  }
  
  /**
   * Sends all accumulated requests. 
   * Prints out any errors that occurred during submission.
   * @return True if request is successful, false if any failures occurred.
   * @throws Exception If problems occurred submitting the request. (Note that additional errors
   * could be noted in the response from Google. These are printed out, not thrown.)
   */
  public boolean sendRequest() throws Exception {
    SpreadsheetService sheet = service.getSpreadsheetService();

    // Get the batch feed URL and submit the batch request
    CellFeed feed = sheet.getFeed(spreadsheetURL, CellFeed.class);
    Link batchLink = feed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM);
    URL batchUrl = new URL(batchLink.getHref());
    CellFeed batchResponse = sheet.batch(batchUrl, batchRequest);

    // Print any errors that may have happened.
    boolean success = true;
    for (CellEntry entry : batchResponse.getEntries()) {
      String batchId = BatchUtils.getBatchId(entry);
      if (!BatchUtils.isSuccess(entry)) {
        success = false;
        BatchStatus status = BatchUtils.getBatchStatus(entry);
        String reason = status.getReason();
        String content = status.getContent();
        System.out.format("%s failed. Reason: %s. Content: %s%n", batchId, reason, content);
      }
    }
    return success;
  }
  
  

}
